/****************************************************************************
**
****************************************************************************/

#include <QReadWriteLock>
#include <QProcess>
#include <QDir>
#include <QPushButton>
#include <QImage>
#include <QPainter>
#include <QSettings>

#include "qrencode/qrencode.h"

#include "status/status.h"

#include "util.h"
#include "hciMain.h"
#include "chargeMain.h"
#include "controllerMain.h"
#include "oiovMain.h"
#include "oiovCallback.h"
#include "baseUpdate.h"

#include <QDebug>
#define HCIMAIN_DEBUG

#define START_OR_STOP_TIMEOUT   (100)

static QReadWriteLock StartChargeServiceLock;
static QReadWriteLock StopChargeServiceLock;

//cmd flag
QList<bool> HciMain::start_charge_service_ = {false, false};
QList<bool> HciMain::stop_charge_service_ = {false, false};

HciMain::HciMain(QList<ChargeMain *> *chargelist, QObject *parent) : QThread(parent),
    m_quit(false),
    m_cycle(100),
    current_gun_(kGunNumberMax),
    action_return_(false),
    action_config_(false),
    action_card_(false)
{
    chargeMainList_ = chargelist;

    Initialization();
}

HciMain::~HciMain()
{
    m_quit = true;
    wait();

    for (int i = 0; i < chargeMainList_->size(); i++) {
        delete chargeMainList_->at(i);
    }
}

int HciMain::current_gun() const
{
    return current_gun_;
}

bool HciMain::action_card(void)
{
    return action_card_;
}

void HciMain::set_action_config(bool data)
{
    action_config_ = data;
}

void HciMain::Initialization()
{
    QString gun_number[kGunNumberMax], qr_prefix, qr_post;

    gun_number[kGunNumberA] = baseConfigure_.gun_number(kGunNumberA);
    gun_number[kGunNumberB] = baseConfigure_.gun_number(kGunNumberB);
    qr_prefix = baseConfigure_.qrcode_prefix();
    qr_post = baseConfigure_.qrcode_post();

#ifdef HCIMAIN_DEBUG
    qDebug() << "Gun(A):" << gun_number[kGunNumberA] << "Gun(B):" << gun_number[kGunNumberB] << "QRPrefix:" << qr_prefix << "QRPost:" << qr_post;
#endif

    MakeQRcode(qr_prefix + gun_number[kGunNumberA] + qr_post, "./qrcodeA.png");
    MakeQRcode(qr_prefix + gun_number[kGunNumberB] + qr_post, "./qrcodeB.png");

    baseUIData_.set_qrcode_home(kGunNumberA, "border-image: url(./qrcodeA.png);");
    baseUIData_.set_qrcode_home(kGunNumberB, "border-image: url(./qrcodeB.png);");
}

bool HciMain::StartChargeService(quint8 gunno)
{
    bool res = false;

    StartChargeServiceLock.lockForRead();
    res = start_charge_service_.at(gunno);
    StartChargeServiceLock.unlock();

    return res;
}

void HciMain::SetStartChargeService(quint8 gunno)
{
    StartChargeServiceLock.lockForWrite();
    start_charge_service_.replace(gunno, true);
    StartChargeServiceLock.unlock();
}

void HciMain::ClearStartChargeService(quint8 gunno)
{
    StartChargeServiceLock.lockForWrite();
    start_charge_service_.replace(gunno, false);
    StartChargeServiceLock.unlock();
}

bool HciMain::StopChargeService(quint8 gunno)
{
    bool res = false;

    StopChargeServiceLock.lockForRead();
    res = stop_charge_service_.at(gunno);
    StopChargeServiceLock.unlock();

    return res;
}

void HciMain::SetStopChargeService(quint8 gunno)
{
    StopChargeServiceLock.lockForWrite();
    stop_charge_service_.replace(gunno, true);
    StopChargeServiceLock.unlock();
}

void HciMain::ClearStopChargeService(quint8 gunno)
{
    StopChargeServiceLock.lockForWrite();
    stop_charge_service_.replace(gunno, false);
    StopChargeServiceLock.unlock();
}

void HciMain::run()
{
    bool fault = false;
    uint16_t dtCount = 0, demand_vol = 0, demand_cur = 0;

    QString info;
    quint32 startChargingtimeout = START_OR_STOP_TIMEOUT, startChargingtimeoutCount = 0;
    quint32 stopChargingtimeout = START_OR_STOP_TIMEOUT, stopChargingtimeoutCount = 0;

    while (!m_quit) {
        if (++dtCount >= 1000 / m_cycle) {
            dtCount = 0;
            emit UpdateDateTime();
        }

        /*---------------------------------------------------------------------------------------------------------------------------------------------*/

        if (OiovResMain::net_state()) {
            baseUIData_.set_net_state(1);
        } else {
            baseUIData_.set_net_state(0);
        }

        /*---------------------------------------------------------------------------------------------------------------------------------------------*/

        switch (BaseUpdate::state()) {
        case BaseUpdate::kInvalid:
            break;
        case BaseUpdate::kUpdateing:
            baseUIData_.set_update_progress(BaseUpdate::progress());

            emit ChangePage(kUpdatePage);
            emit UpdateData(baseUIData_);

            msleep(m_cycle);

            continue;
        case BaseUpdate::kSuccess:
            BaseUpdate::set_state(BaseUpdate::kInvalid);

            emit ChangePage(kHomePage);

            break;
        case BaseUpdate::kFailed:
            BaseUpdate::set_state(BaseUpdate::kInvalid);

            emit ChangePage(kHomePage);

            break;
        default:
            break;
        }

        /*---------------------------------------------------------------------------------------------------------------------------------------------*/

        if (ControllerSendMain::heartbeat_count() > 15) {
            fault = true;
            info = tr("故障： ") + tr("充电桩内部通信异常");
            baseUIData_.set_info_warning(info);

            emit ChangePage(kFaultPage);
            emit UpdateData(baseUIData_);

            msleep(m_cycle);
            continue;
        } else {
            if (fault) {
                fault = false;

                emit ChangePage(kHomePage);
            }
        }

        /*---------------------------------------------------------------------------------------------------------------------------------------------*/

        if ((kGunNumberA != current_gun_) && (kGunNumberB != current_gun_)) {
            baseUIData_.set_text_home(kGunNumberA, baseConfigure_.apu24(kGunNumberA) ? tr("A 枪 (24V)") : tr("A 枪 (12V)"));
            switch (chargeMainList_->at(kGunNumberA)->gun()->state()) {
            case Status::kIdle:
                baseUIData_.set_qrcode_home(kGunNumberA, "border-image: url(:/img/img/anyo_line.jpg);");
                baseUIData_.set_state_home(kGunNumberA, tr("请插枪"));
                break;
            case Status::kReady:
                baseUIData_.set_qrcode_home(kGunNumberA, "border-image: url(./qrcodeA.png);");
                baseUIData_.set_state_home(kGunNumberA, tr("请扫码"));
                break;
            case Status::kStarting:
                baseUIData_.set_qrcode_home(kGunNumberA, "border-image: url(:/img/img/anyo_line.jpg);");
                baseUIData_.set_state_home(kGunNumberA, tr("启动中"));
                break;
            case Status::kCharging:
                baseUIData_.set_qrcode_home(kGunNumberA, "border-image: url(:/img/img/anyo_line.jpg);");
                baseUIData_.set_state_home(kGunNumberA, tr("充电中"));
                break;
            case Status::kStoping:
                baseUIData_.set_qrcode_home(kGunNumberA, "border-image: url(:/img/img/anyo_line.jpg);");
                baseUIData_.set_state_home(kGunNumberA, tr("停止中"));
                break;
            case Status::kFinish:
                baseUIData_.set_qrcode_home(kGunNumberA, "border-image: url(:/img/img/anyo_line.jpg);");
                baseUIData_.set_state_home(kGunNumberA, tr("请拔枪"));
                break;
            case Status::kFault:
                baseUIData_.set_qrcode_home(kGunNumberA, "border-image: url(:/img/img/anyo_line.jpg);");
                baseUIData_.set_state_home(kGunNumberA, tr("故障"));
                break;
            default:
                break;
            }

            baseUIData_.set_text_home(kGunNumberB, baseConfigure_.apu24(kGunNumberB) ? tr("B 枪 (24V)") : tr("B 枪 (12V)"));
            switch (chargeMainList_->at(kGunNumberB)->gun()->state()) {
            case Status::kIdle:
                baseUIData_.set_qrcode_home(kGunNumberB, "border-image: url(:/img/img/anyo_line.jpg);");
                baseUIData_.set_state_home(kGunNumberB, tr("请插枪"));
                break;
            case Status::kReady:
                baseUIData_.set_qrcode_home(kGunNumberB, "border-image: url(./qrcodeB.png);");
                baseUIData_.set_state_home(kGunNumberB, tr("请扫码"));
                break;
            case Status::kStarting:
                baseUIData_.set_qrcode_home(kGunNumberB, "border-image: url(:/img/img/anyo_line.jpg);");
                baseUIData_.set_state_home(kGunNumberB, tr("启动中"));
                break;
            case Status::kCharging:
                baseUIData_.set_qrcode_home(kGunNumberB, "border-image: url(:/img/img/anyo_line.jpg);");
                baseUIData_.set_state_home(kGunNumberB, tr("充电中"));
                break;
            case Status::kStoping:
                baseUIData_.set_qrcode_home(kGunNumberB, "border-image: url(:/img/img/anyo_line.jpg);");
                baseUIData_.set_state_home(kGunNumberB, tr("停止中"));
                break;
            case Status::kFinish:
                baseUIData_.set_qrcode_home(kGunNumberB, "border-image: url(:/img/img/anyo_line.jpg);");
                baseUIData_.set_state_home(kGunNumberB, tr("请拔枪"));
                break;
            case Status::kFault:
                baseUIData_.set_qrcode_home(kGunNumberB, "border-image: url(:/img/img/anyo_line.jpg);");
                baseUIData_.set_state_home(kGunNumberB, tr("故障"));
                break;
            default:
                break;
            }

            if (!action_config_) {
                emit UpdateData(baseUIData_);
            } else {
                if (0x01 == ControllerParserMain::con_feedback_sys_set[kGunNumberA].set_result) {
                    memset(&(ControllerParserMain::con_feedback_sys_set[kGunNumberA]), 0x00, sizeof(ControllerParserMain::con_feedback_sys_set[kGunNumberA]));

#ifdef HCIMAIN_DEBUG
                    qDebug() << "[HCI]-> Write Config Success";
#endif

                    baseUIData_.set_sys_config_info(tr("写配置成功"));

                    emit ShowSysConfigData(baseUIData_);
                } else if (0x02 == ControllerParserMain::con_feedback_sys_set[kGunNumberA].set_result) {
                    memset(&(ControllerParserMain::con_feedback_sys_set[kGunNumberA]), 0x00, sizeof(ControllerParserMain::con_feedback_sys_set[kGunNumberA]));

#ifdef HCIMAIN_DEBUG
                    qDebug() << "[HCI]-> Write Config Failed";
#endif

                    baseUIData_.set_sys_config_info(tr("写配置失败"));

                    emit ShowSysConfigData(baseUIData_);
                }

                baseUIData_.set_gun_main_positive_relay(kGunNumberA, ControllerParserMain::con_feedback_system_check.bit0);
                baseUIData_.set_gun_main_negative_relay(kGunNumberA, ControllerParserMain::con_feedback_system_check.bit1);
                baseUIData_.set_gun_main_positive_relay(kGunNumberB, ControllerParserMain::con_feedback_system_check.bit2);
                baseUIData_.set_gun_main_negative_relay(kGunNumberB, ControllerParserMain::con_feedback_system_check.bit3);
                baseUIData_.set_aps_positive_relay(kGunNumberA, ControllerParserMain::con_feedback_system_check.bit4);
                baseUIData_.set_aps_negative_relay(kGunNumberA, ControllerParserMain::con_feedback_system_check.bit5);
                baseUIData_.set_aps_positive_relay(kGunNumberB, ControllerParserMain::con_feedback_system_check.bit6);
                baseUIData_.set_aps_negative_relay(kGunNumberB, ControllerParserMain::con_feedback_system_check.bit7);
                baseUIData_.set_estop_feedback(ControllerParserMain::con_feedback_system_check.estop_feedback);
                baseUIData_.set_electronic_lock(kGunNumberA, ControllerParserMain::con_feedback_system_check.bit9);
                baseUIData_.set_electronic_lock(kGunNumberB, ControllerParserMain::con_feedback_system_check.bit10);
                baseUIData_.set_access_control_feedback(ControllerParserMain::con_feedback_system_check.access_control_feedback);
                baseUIData_.set_contactor_relay(ControllerParserMain::con_feedback_system_check.contactor_relay);
                baseUIData_.set_model_parallel_main_positive_relay(ControllerParserMain::con_feedback_system_check.model_parallel_main_positive_relay);
                baseUIData_.set_model_parallel_main_negative_relay(ControllerParserMain::con_feedback_system_check.model_parallel_main_negative_relay);
                baseUIData_.set_led_feedback(ControllerParserMain::con_feedback_system_check.led_feedback);
                baseUIData_.set_gun_head_temp_feedback(kGunNumberA, ControllerParserMain::con_feedback_system_check.bit16);
                baseUIData_.set_gun_head_temp_feedback(kGunNumberB, ControllerParserMain::con_feedback_system_check.bit17);
                baseUIData_.set_meter_feedback(kGunNumberA, ControllerParserMain::con_feedback_system_check.bit18);
                baseUIData_.set_meter_feedback(kGunNumberB, ControllerParserMain::con_feedback_system_check.bit19);
                baseUIData_.set_card_feedback(ControllerParserMain::con_feedback_system_check.card_feedback);
                baseUIData_.set_gun_can_feedback(kGunNumberA, ControllerParserMain::con_feedback_system_check.bit21);
                baseUIData_.set_gun_can_feedback(kGunNumberB, ControllerParserMain::con_feedback_system_check.bit22);
                baseUIData_.set_model_can_feedback(ControllerParserMain::con_feedback_system_check.model_can_feedback);
                baseUIData_.set_fan_feedback(kGunNumberA, ControllerParserMain::con_feedback_system_check.bit25);
                baseUIData_.set_fan_feedback(kGunNumberB, ControllerParserMain::con_feedback_system_check.bit26);

                emit ShowSysCheckData(baseUIData_);
            }

            msleep(m_cycle);
            continue;
        }

        /*---------------------------------------------------------------------------------------------------------------------------------------------*/

        if (Status::kStarting != chargeMainList_->at(current_gun_)->gun()->state()) {
            startChargingtimeout = START_OR_STOP_TIMEOUT;
        } else {
            ++startChargingtimeoutCount;
        }
        if (Status::kStoping != chargeMainList_->at(current_gun_)->gun()->state()) {
            stopChargingtimeout = START_OR_STOP_TIMEOUT;
        } else {
            ++stopChargingtimeoutCount;
        }

        switch (chargeMainList_->at(current_gun_)->gun()->state()) {
        case Status::kIdle:
            baseUIData_.set_qrcode_home(current_gun_, "border-image: url(:/img/img/anyo_line.jpg);");
            baseUIData_.set_qrcode_card(baseUIData_.qrcode_home(current_gun_));
            if (kGunNumberA == current_gun_) {
                baseUIData_.set_info_card(tr("请将 A 枪连接到电动车"));
            } else if (kGunNumberB == current_gun_) {
                baseUIData_.set_info_card(tr("请将 B 枪连接到电动车"));
            } else {
                //...
            }

            action_return_ = false;
            action_card_ = true;

            startChargingtimeout = START_OR_STOP_TIMEOUT;
            startChargingtimeoutCount = 0;
            stopChargingtimeout = START_OR_STOP_TIMEOUT;
            stopChargingtimeoutCount = 0;
            break;
        case Status::kReady:
            if (kGunNumberA == current_gun_) {
                baseUIData_.set_qrcode_home(kGunNumberA, "border-image: url(./qrcodeA.png);");
                baseUIData_.set_qrcode_card(baseUIData_.qrcode_home(kGunNumberA));
                baseUIData_.set_info_card(tr("请扫码或刷卡开始充电"));
            } else if (kGunNumberB == current_gun_) {
                baseUIData_.set_qrcode_home(kGunNumberB, "border-image: url(./qrcodeB.png);");
                baseUIData_.set_qrcode_card(baseUIData_.qrcode_home(kGunNumberB));
                baseUIData_.set_info_card(tr("请扫码或刷卡开始充电"));
            } else {
                //...
            }

            action_return_ = false;
            action_card_ = true;

            startChargingtimeout = START_OR_STOP_TIMEOUT;
            startChargingtimeoutCount = 0;
            stopChargingtimeout = START_OR_STOP_TIMEOUT;
            stopChargingtimeoutCount = 0;
            break;
        case Status::kStarting:
            baseUIData_.set_info_identify(tr("开启充电中，请勿拔枪..."));
            if (startChargingtimeoutCount >= 1000 / m_cycle) {
                startChargingtimeoutCount = 0;
                if (startChargingtimeout > 0) {
                    --startChargingtimeout;
                }
            }
            baseUIData_.set_timeout_identify(QString::number(startChargingtimeout) + " 秒");

            action_return_ = false;
            action_card_ = false;

            emit ChangePage(kStartOrStopPage);
            break;
        case Status::kCharging:
            if (kGunNumberA == current_gun_) {
                baseUIData_.set_sn_charging(tr("A 枪"));
            } else if (kGunNumberB == current_gun_) {
                baseUIData_.set_sn_charging(tr("B 枪"));
            } else {
                baseUIData_.set_sn_charging(" ");
            }
            baseUIData_.set_soc_charging(OiovCallback::ops_property_charge_data[current_gun_].soc);
            baseUIData_.set_cur_charging(OiovCallback::ops_property_charge_data[current_gun_].output_current); //1%10
            baseUIData_.set_vol_charging(OiovCallback::ops_property_charge_data[current_gun_].output_voltage); //1%10
            baseUIData_.set_elect_charging(OiovCallback::ops_property_charge_data[current_gun_].charging_elect / 100); //1%100
            baseUIData_.set_time_charging(chargeMainList_->at(current_gun_)->gun()->charge_time());
            baseUIData_.set_max_temp(OiovCallback::ops_property_charge_data[current_gun_].battery_max_temp - 50);
            //...
            demand_cur = ControllerParserMain::con_telemetry[current_gun_].demand_cur;
            if (4000 >= demand_cur) {
                baseUIData_.set_demand_cur(4000 - demand_cur); //1%10
            }
            demand_vol = ControllerParserMain::con_telemetry[current_gun_].demand_vol;
            baseUIData_.set_demand_vol(demand_vol); //1%10

            if (!action_return_) {
                emit ChangePage(kChargingPage);
            }
            action_card_ = true;
            break;
        case Status::kStoping:
            baseUIData_.set_info_identify(tr("充电停机中，请勿拔枪..."));
            if (stopChargingtimeoutCount >= 1000 / m_cycle) {
                stopChargingtimeoutCount = 0;
                if (stopChargingtimeout > 0) {
                    --stopChargingtimeout;
                }
            }
            baseUIData_.set_timeout_identify(QString::number(stopChargingtimeout) + " 秒");

            action_return_ = false;
            action_card_ = false;

            emit ChangePage(kStartOrStopPage);
            break;
        case Status::kFinish:
            if (kGunNumberA == current_gun_) {
                baseUIData_.set_sn_chargend(tr("A 枪"));
            } else if (kGunNumberB == current_gun_) {
                baseUIData_.set_sn_chargend(tr("B 枪"));
            } else {
                baseUIData_.set_sn_chargend(tr(" "));
            }
            baseUIData_.set_soc_chargend(OiovCallback::ops_property_charge_data[current_gun_].soc);
            baseUIData_.set_elect_chargend(OiovCallback::ops_property_charge_data[current_gun_].charging_elect / 100); //1%100
            baseUIData_.set_time_chargend(chargeMainList_->at(current_gun_)->gun()->charge_time());
            ShowStopResultInfo(current_gun_);

            if (!action_return_) {
                emit ChangePage(kFinishPage);
            }
            action_card_ = false;
            break;
        case Status::kFault:
            ShowFaultInfo(current_gun_);

            if (!action_return_) {
                emit ChangePage(kFaultPage);
            }
            action_card_ = false;
            break;
        default:
            break;
        }

        emit UpdateData(baseUIData_);

        msleep(m_cycle);
    }
}

void HciMain::ShowFaultInfo(int gunno)
{
    if (0x01 == ControllerParserMain::con_telecommand[gunno].scram_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 急停按钮被按下"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].door_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 门被打开"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].ac_breaker_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 交流断路器异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].output_con_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 直流母线输出接触器异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].dc_bus_out_fuse_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 直流母线输出熔断器异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].electronic_lock_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 充电接口电子锁异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_fan_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 充电机风扇异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].battery_vol_overtop) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 电池电压过高"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].insulation_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 绝缘检测异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].batter_transp_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 电池反接"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].bus_ct_guid_alarm) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 充电中车辆控制引导异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_over_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 充电桩过温"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_gun_over_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 充电枪过温"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charger_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 充电枪未归位"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].bms_com_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： BMS通信异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].input_over_vol) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 输入电压过压"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].input_under_vol) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 输入电压欠压"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].dc_bus_over_vol_alarm) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 直流母线输出过压"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].dc_bus_under_vol_alarm) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 直流母线输出欠压"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].dc_bus_over_cur_alarm) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 直流母线输出过流"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_mod_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 充电模块异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_mod_ac_input_alarm) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 充电模块交流输入异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_mod_input_over_vol_alarm) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 充电模块输入过压"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_mod_input_under_vol_alarm) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 充电模块输入欠压"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_mod_input_phase_alarm) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 充电模块输入缺相"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_mod_out_short_cir_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 充电模块输出短路"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_mod_out_over_cur_alarm) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 充电模块输出过流"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_mod_out_over_vol_alarm) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 充电模块输出过压"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_mod_out_under_vol_alarm) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 充电模块输出欠压"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_mod_over_temp_alarm) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 充电模块过温"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_mod_com_alarm) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 充电模块通信异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_mod_fan_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 充电模块风扇异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_emp_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 充电桩充电枪座异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].meter_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 电表异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].insult_module_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 绝缘模块异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].bleed_fault) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("故障： 泄放异常"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].charg_para_no) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 充电参数未分配"));
    } else if (0x01 == ControllerParserMain::con_telecommand[gunno].battery_vol_inconformity) {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("告警： 电池电压不匹配"));
    } else {
        baseUIData_.set_type_warning("define");
        baseUIData_.set_info_warning(tr("发生了未知的告警或故障，请在右上角点击 <主界面> 返回"));
    }
}

void HciMain::ShowStopResultInfo(int gunno)
{
    QString result = tr("");
    quint16 faultCode = 0;

    switch (ControllerParserMain::con_charg_stop_result[gunno].result_code) {
    case 0x01:
        baseUIData_.set_result_chargend(result + tr("用户停止充电"));
        break;
    case 0x02:
        //0x02
        switch (ControllerParserMain::con_charg_stop_result[gunno].fault_code_one) {
        case 0x01:
            baseUIData_.set_result_chargend(result + tr("急停故障"));
            break;
        case 0x02:
            baseUIData_.set_result_chargend(result + tr("门锁被打开"));
            break;
        case 0x04:
            baseUIData_.set_result_chargend(result + tr("绝缘模块故障"));
            break;
        case 0x08:
            baseUIData_.set_result_chargend(result + tr("电表故障"));
            break;
        case 0x10:
            baseUIData_.set_result_chargend(result + tr("主正继电器故障"));
            break;
        case 0x20:
            baseUIData_.set_result_chargend(result + tr("BMS通讯故障"));
            break;
        case 0x40:
            baseUIData_.set_result_chargend(result + tr("充电模块故障"));
            break;
        case 0x80:
            baseUIData_.set_result_chargend(result + tr("主负继电器故障"));
            break;
        default:
            switch (ControllerParserMain::con_charg_stop_result[gunno].fault_code_two) {
            case 0x01:
                baseUIData_.set_result_chargend(result + tr("电子锁故障"));
                break;
            case 0x02:
                baseUIData_.set_result_chargend(result + tr("绝缘故障"));
                break;
            case 0x04:
                baseUIData_.set_result_chargend(result + tr("并联正继电器故障"));
                break;
            case 0x08:
                baseUIData_.set_result_chargend(result + tr("并联负继电器故障"));
                break;
            case 0x10:
                baseUIData_.set_result_chargend(result + tr("电池电压不匹配"));
                break;
            case 0x20:
                baseUIData_.set_result_chargend(result + tr("电池电流过高"));
                break;
            case 0x40:
                baseUIData_.set_result_chargend(result + tr("无电池电压"));
                break;
            case 0x80:
                baseUIData_.set_result_chargend(result + tr("电池反接故障"));
                break;
            default:
                faultCode =
                    (ControllerParserMain::con_charg_stop_result[gunno].fault_code_one << 0x08) +
                    (ControllerParserMain::con_charg_stop_result[gunno].fault_code_two);
                baseUIData_.set_result_chargend(result + tr("充电机故障，执行主动终止充电") + "(0x" + QString::number(faultCode, 16).toUpper() + ")");
                break;
            }
            break;
        }
        break;
    case 0x03:
        //0x03
        if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_spn2560xx_timeout.spn256000_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收CRM00超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_spn2560xx_timeout.spn2560aa_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收CRMAA超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_tmra_timeout.timesync_and_maxpower_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收CML超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_tmra_timeout.ready_charg_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收CRO超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_cscs_timeout.charg_status_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收CCS超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_cscs_timeout.charg_stop_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收CST超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_csbo_timeout.charg_statistics_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收CSD超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_csbo_timeout.bms_other_error) {
            baseUIData_.set_result_chargend(result + tr("接收其他充电机报文超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_timeout.bms_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收BRM超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_bpbrc_timeout.battery_param_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收BCP超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_bpbrc_timeout.bms_ready_charg_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收BRO超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_bsbcbsc_timeout.batter_status_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收BCS超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_bsbcbsc_timeout.batter_charg_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收BCL超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_bsbcbsc_timeout.bms_stop_charg_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收BST超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_bscoe_timeout.bms_statistics_timeout) {
            baseUIData_.set_result_chargend(result + tr("接收BSD超时"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_bscoe_timeout.charg_other_error) {
            baseUIData_.set_result_chargend(result + tr("接收BRO超时"));
        } else {
            baseUIData_.set_result_chargend(result + tr("判定BMS异常，执行主动终止充电"));
        }
        break;
    case 0x04:
        //0x04
        if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_reason_code.bms_reason_code_soc) {
            baseUIData_.set_result_chargend(result + tr("达到所需求的SOC目标值"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_reason_code.bms_reason_code_bms_vol) {
            baseUIData_.set_result_chargend(result + tr("达到总电压的设定值"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_reason_code.bms_reason_code_vol) {
            baseUIData_.set_result_chargend(result + tr("达到单体电压的设定值"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_reason_code.bms_reason_code_stop) {
            baseUIData_.set_result_chargend(result + tr("充电机主动终止"));
        } else {
            baseUIData_.set_result_chargend(result + tr("BMS正常终止充电"));
        }
        break;
    case 0x05:
        //0x05
        if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_fault_code.bms_fault_code_insulation) {
            baseUIData_.set_result_chargend(result + tr("绝缘故障"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_fault_code.bms_fault_code_out_link_overtemp) {
            baseUIData_.set_result_chargend(result + tr("输出连接器过温故障"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_fault_code.bms_fault_code_bms_overtemp) {
            baseUIData_.set_result_chargend(result + tr("BMS元器件过温故障"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_fault_code.bms_fault_code_charg_link) {
            baseUIData_.set_result_chargend(result + tr("充电连接器故障"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_fault_code.bms_fault_code_battery_overtemp) {
            baseUIData_.set_result_chargend(result + tr("电池组温度过高故障"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_fault_code.bms_fault_code_hv_relay) {
            baseUIData_.set_result_chargend(result + tr("高压继电器故障"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_fault_code.bms_fault_code_cc2) {
            baseUIData_.set_result_chargend(result + tr("检测点2电压检测故障"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_fault_code.bms_fault_code_other) {
            baseUIData_.set_result_chargend(result + tr("其他BMS故障"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_error_code.bms_error_code_cur) {
            baseUIData_.set_result_chargend(result + tr("电流过大"));
        } else if (0x01 == ControllerParserMain::con_charg_stop_result[gunno].con_bms_error_code.bms_error_code_vol) {
            baseUIData_.set_result_chargend(result + tr("电压异常"));
        } else {
            baseUIData_.set_result_chargend(result + tr("BMS异常/故障终止充电"));
        }
        break;
    default:
        baseUIData_.set_result_chargend(result + tr("未知"));
        break;
    }
}

void HciMain::HandleButton()
{
    QPushButton *obj = (QPushButton *)sender();
    QString button_name = obj->objectName();

#ifdef HCIMAIN_DEBUG
    qDebug() << "[HCI]-> active button:" << button_name;
#endif

    if ("HPCardAPB" == button_name || "HPQRAPushButton" == button_name) {
        current_gun_ = kGunNumberA;
        switch (chargeMainList_->at(current_gun_)->gun()->state()) {
        case Status::kIdle:
            baseUIData_.set_qrcode_home(current_gun_, "border-image: url(:/img/img/anyo_line.jpg);");
            baseUIData_.set_qrcode_card(baseUIData_.qrcode_home(current_gun_));
            baseUIData_.set_info_card(tr("请将充电枪连接到电动车"));
            baseUIData_.set_sn_card(BaseConfigure::gun_number(current_gun_));

            emit ChangePage(kCardPage);

            break;
        case Status::kReady:
            baseUIData_.set_qrcode_home(current_gun_, "border-image: url(./qrcodeA.png);");
            baseUIData_.set_qrcode_card(baseUIData_.qrcode_home(current_gun_));
            baseUIData_.set_info_card(tr("请扫码或刷卡开始充电"));
            baseUIData_.set_sn_card(BaseConfigure::gun_number(current_gun_));

            action_card_ = true;

            emit ChangePage(kCardPage);

            break;
        case Status::kStarting:
            break;
        case Status::kCharging:
            action_return_ = false;
            action_card_ = true;

            emit ChangePage(kChargingPage);

            break;
        case Status::kStoping:
            break;
        case Status::kFinish:
            action_return_ = false;
            action_card_ = false;

            emit ChangePage(kFinishPage);

            break;
        case Status::kFault:
            action_return_ = false;
            action_card_ = false;

            emit ChangePage(kFaultPage);

            break;
        default:
            break;
        }
    } else if ("HPCardBPB" == button_name || "HPQRBPushButton" == button_name) {
        current_gun_ = kGunNumberB;
        switch (chargeMainList_->at(current_gun_)->gun()->state()) {
        case Status::kIdle:
            baseUIData_.set_qrcode_home(current_gun_, "border-image: url(:/img/img/anyo_line.jpg);");
            baseUIData_.set_qrcode_card(baseUIData_.qrcode_home(current_gun_));
            baseUIData_.set_info_card(tr("请将充电枪连接到电动车"));
            baseUIData_.set_sn_card(BaseConfigure::gun_number(current_gun_));

            emit ChangePage(kCardPage);

            break;
        case Status::kReady:
            baseUIData_.set_qrcode_home(current_gun_, "border-image: url(./qrcodeB.png);");
            baseUIData_.set_qrcode_card(baseUIData_.qrcode_home(current_gun_));
            baseUIData_.set_info_card(tr("请扫码或刷卡开始充电"));
            baseUIData_.set_sn_card(BaseConfigure::gun_number(current_gun_));

            action_card_ = true;

            emit ChangePage(kCardPage);

            break;
        case Status::kStarting:
            break;
        case Status::kCharging:
            action_return_ = false;
            action_card_ = true;

            emit ChangePage(kChargingPage);

            break;
        case Status::kStoping:
            break;
        case Status::kFinish:
            action_return_ = false;
            action_card_ = false;

            emit ChangePage(kFinishPage);

            break;
        case Status::kFault:
            action_return_ = false;
            action_card_ = false;

            emit ChangePage(kFaultPage);

            break;
        default:
            break;
        }
    } else if ("HPVinAPB" == button_name) {
        //...
    } else if ("HPVinBPB" == button_name) {
        //...
    } else if ("DPStartPB" == button_name) {
#ifdef HCIMAIN_DEBUG
        qDebug() << "[HCI]->" << (kGunNumberA == current_gun_ ? "No.a" : "No.b") << "start charge...";
#endif
        switch (chargeMainList_->at(current_gun_)->gun()->state()) {
        case Status::kReady:
            SetStartChargeService(current_gun_);
            break;
        default:
            break;
        }
    } else if ("DPReturnHomePB" == button_name) {
        current_gun_ = kGunNumberMax;

        emit ChangePage(kHomePage);
    } else if ("CPStopPB" == button_name) {
#ifdef HCIMAIN_DEBUG
        qDebug() << "[HCI]->" << (kGunNumberA == current_gun_ ? "No.a" : "No.b") << "stop charging...";
#endif
        switch (chargeMainList_->at(current_gun_)->gun()->state()) {
        case Status::kCharging:
            SetStopChargeService(current_gun_);
            break;
        default:
            break;
        }
    } else if ("CPReturnHomePB" == button_name) {
        current_gun_ = kGunNumberMax;

        action_return_ = true;
        action_card_ = false;

        emit ChangePage(kHomePage);
    } else if ("FPReturnHomePB" == button_name) {
        current_gun_ = kGunNumberMax;

        action_return_ = true;
        action_card_ = false;

        emit ChangePage(kHomePage);
    } else if ("TPReturnHomePB" == button_name) {
        current_gun_ = kGunNumberMax;

        action_return_ = true;
        action_card_ = false;

        emit ChangePage(kHomePage);
    } else if ("LocalUpdatePrePB" == button_name) {
        QString path = "/mnt/sda1/tcu_update";
        QDir dir(path);
        if (!dir.exists()) {
            baseUIData_.set_local_update_info("提示：请根据上述提示检查 U 盘是否包含有效路径");

            emit UpdateData(baseUIData_);

            return;
        }
        QString name = "/mnt/sda1/tcu_update/tcu";
        QFile file(name);
        if (!file.exists()) {
            baseUIData_.set_local_update_info("提示：请根据上述提示检查 U 盘是否包含有效文件");

            emit UpdateData(baseUIData_);

            return;
        }
        baseUIData_.set_local_update_info("提示：前置检测完成，结果有效。请执行 <本地升级> 。");
    } else if ("LocalUpdatePB" == button_name) {
        QString name = "/mnt/sda1/tcu_update/tcu";
        QFile file(name);
        if (!file.exists()) {
            baseUIData_.set_local_update_info("提示：执行 <本地升级> 前，请执行 <前置检测> 。");

            emit UpdateData(baseUIData_);

            return;
        }
        QString new_name = "/root/ota/tcu";
        if (file.copy(new_name)) {
            QProcess::execute("reboot");
        }
    } else {
        current_gun_ = kGunNumberMax;
    }

    emit UpdateData(baseUIData_);
}

void HciMain::ShowConfigPage()
{
    action_config_ = true;

    emit ChangePage(kConfigPage);
    emit UpdateData(baseUIData_);

    baseUIData_.set_sys_config_info("");
    emit ShowSysConfigData(baseUIData_);
}

void HciMain::MakeQRcode(const QString& qrData, const QString& saveName)
{
    if (nullptr == qrData) {
        return;
    }

    QRcode *qrcode = QRcode_encodeString(qrData.toUtf8().data(), 1, QR_ECLEVEL_H, QR_MODE_8, 1);
    if (nullptr == qrcode) {
        return;
    }

    QImage image(QSize(512, 512), QImage::Format_Mono);
    QPainter painter(&image);

    QColor colorFG("#000000");
    QColor colorBG("#ffffff");

    painter.setBrush(colorBG);
    painter.setPen(Qt::NoPen);
    painter.drawRect(0, 0, image.width(), image.height());
    painter.setBrush(colorFG);

    const double width = (qrcode->width > 0) ? (qrcode->width) : (1);
    const double aspect = image.width() / image.height();
    const double scale = ((aspect > 1.0) ? image.height() : image.width()) / width;

    for (int y = 0; y < width; y++) {
        const int yy = y * width;
        for (int x = 0; x < width; x++) {
            const int xx = yy + x;
            const unsigned char b = qrcode->data[xx];

            if (b & 0x01) {
                const double rx1 = x * scale, ry1 = y * scale;
                QRectF rectF(rx1, ry1, scale, scale);
                painter.drawRects(&rectF, 1);
            }
        }
    }

    image.save(saveName, nullptr, -1);

    QRcode_free(qrcode);
}
